/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2018-2019.
 * Description: support rtos mode switch
 * Author: zhoumansuo <zhoumansuo@huawei.com>
 * Create: 2018-10-22
 */

#include <linux/linkage.h>
#include <linux/init.h>
#include <linux/io.h>
#include <mach/slave_core.h>

#define nosec_writel(a, b)	writel(a, (volatile void __iomem *)b)
#define nosec_readl(a)	readl((volatile void __iomem *)a)

static void set_nosec(void)
{
	register unsigned int value;

	/* Invalidate all instruction caches, and unified TLB */
	value = 0;
	asm volatile ("mcr p15, 0, %0, c7, c5, 0" : : "r" (value));
	asm volatile ("mcr p15, 0, %0, c8, c7, 0" : : "r" (value));
	/* Branch predictor invalidate all */
	asm volatile ("mcr p15, 0, %0, c7, c5, 6" : : "r" (value));

	/* Eanble the non sec access of CP10, CP11, and ACTLR.SMP */
	asm volatile ("mrc p15, 0, %0, c1, c1, 2" : "=r" (value));
	value = value | (1 << 10) | (1 << 11) | (1 << 17) | (1 << 18);
	asm volatile ("mcr p15, 0, %0, c1, c1, 2" : : "r" (value));

	/* set scr */
	asm volatile ("mrc p15, 0, %0, c1, c1, 0" : "=r" (value));
	value = value | (1 << 0) | (1 << 7) | (1 << 8);
	asm volatile ("mcr p15, 0, %0, c1, c1, 0" : : "r" (value));
}

int slave_core_need_nonsec(void)
{
	const unsigned int base = 0x000000;
	const int need_nonsec = nosec_readl(base + HISI_SLAVECORE_NONSEC);

	return need_nonsec;
}

/* switch to no-secure for slave core */
void hisi_switch_nonsec(void)
{
	if (slave_core_need_nonsec())
		set_nosec();
}
